//////////////////////////////////////////////////////////////////////////
// $Id: MConfig.cpp,v 1.1 2009/04/03 12:46:10 sunjun Exp $
//////////////////////////////////////////////////////////////////////////

#include "Local.h"
#include "xml/tinyxml.h"

//////////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////////

NAMESPACE_BEGIN

//////////////////////////////////////////////////////////////////////////

	MConfig::MConfig()
	{
		GUARD(MConfig::MConfig);

		UNGUARD;
	}

	MConfig::~MConfig()
	{
		GUARD(MConfig::~MConfig);

		UNGUARD;
	}
	
	//////////////////////////////////////////////////////////////////////////

	/*
	====================
	setValue
	====================
	*/
	INLINE VOID MConfig::setValue( const CHAR* value )
	{
		GUARD(MConfig::setValue);

		mValue = value;

		UNGUARD;
	}

	/*
	====================
	getValue
	====================
	*/
	INLINE const CHAR* MConfig::getValue() const
	{
		GUARD(MConfig::getValue);

		return mValue.c_str();

		UNGUARD;
	}

	/*
	====================
	setText
	====================
	*/
	INLINE VOID MConfig::setText( const CHAR* text )
	{
		GUARD(MConfig::setText);

		mText = text;

		UNGUARD;
	}

	/*
	====================
	getText
	====================
	*/
	INLINE const CHAR* MConfig::getText() const
	{
		GUARD(MConfig::getText);

		return mText.c_str();

		UNGUARD;
	}

	/*
	====================
	setAttribute
	====================
	*/
	INLINE VOID MConfig::setAttribute( const CHAR* name, const CHAR* value )
	{
		GUARD(MConfig::setAttribute);

		std::map<Str,Str>::iterator it = mAttributes.find(name);
		CHECK(it==mAttributes.end()&&"The attribute is existent already!\n");
		mAttributes.insert( std::map<Str, Str>::value_type(name, value) );

		UNGUARD;
	}	

	/*
	====================
	getAttribute
	====================
	*/
	INLINE const CHAR* MConfig::getAttribute( const CHAR* name ) const
	{
		GUARD(MConfig::getAttribute);

		std::map<Str,Str>::const_iterator it = mAttributes.find(name);
		if(it!=mAttributes.end()) return it->second.c_str();
		return "";

		UNGUARD;
	}

	/*
	====================
	setChild
	====================
	*/
	INLINE VOID MConfig::setChild( const MConfig * child )
	{
		GUARD(MConfig::setChild);
		
		CHECK(child);
		mChildren.push_back((MConfig*)child);

		UNGUARD;
	}

	/*
	====================
	getChild
	====================
	*/
	INLINE const MConfig * MConfig::getChild( U32 i ) const
	{
		GUARD(MConfig::getChild);

		if( i >= mChildren.size() ) return NULL;
		return mChildren[i].ptr();

		UNGUARD;
	}

	//////////////////////////////////////////////////////////////////////////

	/*
	====================
	parse
	====================
	*/
	INLINE static MConfig * CDECL parse( const TiXmlElement * element_ptr )
	{
		GUARD(parse);

		CHECK( element_ptr );
		MConfig * config_ptr = MNEW(MConfig); CHECK(config_ptr);

		// parse the value of the element
		config_ptr->setValue( element_ptr->Value() );

		// parse the text of the element
		const CHAR * text = element_ptr->GetText();
		if( text ) config_ptr->setText( text );

		// parse the attribute of the element
		for( const TiXmlAttribute* attribute_ptr = element_ptr->FirstAttribute(); attribute_ptr; attribute_ptr = attribute_ptr->Next() )
		{
			config_ptr->setAttribute( attribute_ptr->Name(), attribute_ptr->Value() );
		}

		// parse the children of the element
		for( const TiXmlElement *child_element_ptr = element_ptr->FirstChildElement(); child_element_ptr; child_element_ptr = child_element_ptr->NextSiblingElement() ) 
		{
			config_ptr->setChild( parse( child_element_ptr ) );
		}

		return config_ptr;

		UNGUARD;
	}

	/*
	====================
	load
	====================
	*/
	INLINE MConfig* CDECL MConfig::load( const MData* data )
	{
		GUARD(MConfig::load);

		// xml parse
		TiXmlDocument document;
		document.Parse( (const CHAR*)data->get(), NULL, TIXML_ENCODING_UTF8 );
		CHECK( !document.Error() );
		return parse( document.RootElement() );

		UNGUARD;
	}

//////////////////////////////////////////////////////////////////////////

NAMESPACE_END

//////////////////////////////////////////////////////////////////////////

